using System;
using Microsoft.DirectX.Direct3D;
using System.Drawing;
using SharpWind.Input;

namespace SharpWind.Gui.Controls
{
	public class ComboBox : ButtonBase
	{
		#region ComboBoxButton

		private class ComboBoxButton : ButtonBase
		{
			public event EventHandler Click = null;

			public ComboBoxButton() : base( "combobox" )
			{
				Size = new SizeF( 20, 20 );
			}

			internal override void Render()
			{
				Engine.Instance.Renderer.GuiSprite.Begin( SpriteFlags.AlphaBlend );

				Theme theme = Engine.Instance.Scene.Controls.Theme;
				Theme.Control scrollbar = theme.Controls[this.control];
				Theme.Control.Element element = scrollbar.Elements[this.curentState.ToString() + "Button" ];

				Engine.Instance.Renderer.GuiSprite.Draw2D( theme.Texture.D3DTexture,
														   new Rectangle( element.X, element.Y, element.Width, element.Height ),
														   new SizeF( Size.Width, Size.Height ),
														   new PointF( Location.X, Location.Y ), element.Color );

				Engine.Instance.Renderer.GuiSprite.End();
			}

			protected override void OnMouseDown()
			{
				if( Click != null )
				{
					Click( this, EventArgs.Empty );
				}
			}

			public override PointF Location
			{
				get
				{
					return this.location;
				}
				set
				{
					this.location = value;
				}
			}

			public override SizeF Size
			{
				get
				{
					return this.size;
				}
				set
				{
					this.size = value;
				}

			}
		}

		#endregion

		private ComboBoxButton button = null;

		private Label label = null;

		private ListBox listBox = null;

		private int maxDropDownItems = 8;

		public ComboBox() : base( "combobox" )
		{
			this.label		= new Label();
			this.button  = new ComboBoxButton();
			this.button.Click += new EventHandler( OnButtonClick );
			this.listBox = new ListBox();
			this.listBox.Visible = false;
			this.listBox.SelectedIndexChanged += new EventHandler( OnSelectedIndexChanged );
			this.listBox.Items.ItemAdd += new EventHandler( ChangeListBoxSize );
			this.listBox.Items.ItemRemove += new EventHandler( ChangeListBoxSize );
			Size		 = new SizeF( 120, 20 );
			Font = Engine.Instance.Scene.Controls.Theme.Font;
		}

		private void ChangeListBoxSize( object sender, EventArgs e )
		{
			RecalculateListBox();
		}

		private void OnSelectedIndexChanged( object sender, EventArgs e )
		{
			this.label.Text = Items[SelectedIndex];
			this.listBox.Visible = false;
		}

		private void OnButtonClick( object sender, EventArgs e )
		{
			this.listBox.Visible = true;
		}

		internal override void Render()
		{
			if( Enabled && Visible )
			{
				base.Render();
				this.label.Render();
				this.button.Render();
				this.listBox.Render();
			}
		}

		internal override void MouseDown( MouseEventArgs e )
		{
			if( Enabled && Visible )
			{
				if( this.listBox.Visible )
				{
					RectangleF cb = new RectangleF( Location, Size );
					RectangleF lb = new RectangleF( this.listBox.Location, this.listBox.Size );
					PointF mouse = new PointF( e.AbsX, e.AbsY );

					if( !cb.Contains( mouse ) && !lb.Contains( mouse ) )
					{
						this.listBox.Visible = false;
					}
				}

				this.label.MouseDown( e );
				this.button.MouseDown( e );
				this.listBox.MouseDown( e );
			}
		}

		internal override void MouseMove( MouseEventArgs e )
		{
			if( Enabled && Visible )
			{
				base.MouseMove( e );
				this.label.MouseMove( e );
				this.button.MouseMove( e );
				this.listBox.MouseMove( e );
			}
		}

		internal override void MousePress( MouseEventArgs e )
		{
			if( Enabled && Visible )
			{
				this.label.MousePress( e );
				this.button.MousePress( e );
				this.listBox.MousePress( e );
			}
		}

		internal override void MouseUp( MouseEventArgs e )
		{
			if( Enabled && Visible )
			{
				this.label.MouseUp( e );
				this.button.MouseUp( e );
				this.listBox.MouseUp( e );
			}
		}

		private void RecalculateElements()
		{
			this.label.Location   = new PointF( Location.X + 2, Location.Y + 2 );
			this.label.Size		  = new SizeF( Size.Width - 8 - this.button.Size.Width, Size.Height - 4 );
			this.button.Location  = new PointF( Location.X + Size.Width - button.Size.Width - 3, Location.Y + 4 );
			this.button.Size	  = new SizeF( this.button.Size.Width, Size.Height - 8 );
			this.listBox.Location = new PointF( Location.X, Location.Y + Size.Height + 2 );
			RecalculateListBox();
		}

		private void RecalculateListBox()
		{
			if( this.listBox.Items.Count == 0 )
			{
				this.listBox.ShowVScrollBar = false;
				this.listBox.Size = new SizeF( Size.Width, this.listBox.LineHeight );
				this.label.Text = string.Empty;
			}
			else if( this.listBox.Items.Count <= MaxDropDownItems )
			{
				this.listBox.ShowVScrollBar = false;
				this.listBox.Size = new SizeF( Size.Width, this.listBox.LineHeight * this.listBox.Items.Count + 5 );
				this.label.Text = Items[SelectedIndex];
			}
			else
			{
				this.listBox.ShowVScrollBar = true;
				this.listBox.Size = new SizeF( Size.Width, MaxDropDownItems * this.listBox.LineHeight + 5 );
				this.label.Text = Items[SelectedIndex];
			}
		}

		public SharpWind.Resources.Font Font
		{
			get
			{
				return this.label.Font;
			}
			set
			{
				if( this.label.Font != value )
				{
					this.label.Font	  = value;
					this.listBox.Font = value;
					RecalculateElements();
				}
			}
		}

		public TextAlign TextAlign
		{
			get
			{
				return this.label.TextAlign;
			}
			set
			{
				if( this.label.TextAlign != value )
				{
					this.label.TextAlign = value;
				}
			}
		}

		public Color TextColor
		{
			get
			{
				return this.label.TextColor;
			}
			set
			{
				if( this.label.TextColor != value )
				{
					this.label.TextColor   = value;
					this.listBox.TextColor = value;
					RecalculateElements();
				}
			}
		}

		public override SizeF Size
		{
			get
			{
				return base.Size;
			}
			set
			{
				if( base.Size != value )
				{
					base.Size = value;
					RecalculateElements();
				}
			}
		}

		public override PointF Location
		{
			get
			{
				return base.Location;
			}
			set
			{
				if( base.Location != value )
				{
					base.Location = value;
					RecalculateElements();
				}
			}
		}

		public int MaxDropDownItems
		{
			get
			{
				return this.maxDropDownItems;
			}
			set
			{
				if( value != this.maxDropDownItems && value >= 1 )
				{
					this.maxDropDownItems = value;
					RecalculateListBox();
				}
			}
		}

		public int SelectedIndex
		{
			get
			{
				return this.listBox.SelectedIndex;
			}
		}

		public ObjectCollection<string> Items
		{
			get
			{
				return this.listBox.Items;
			}
		}
	}
}
